#include "Thread.hpp"
#include "BlockQueue.hpp"
#include <unistd.h>
#include <vector>
using namespace ThreadModule;
using namespace std;

/*int g_data=10;
//字面量的生命周期仅限于所在的表达式,字面量是临时对象
//线程的构造函数使用引用接收参数,不可引用字面量
void Consumer(int& data)
{
    while(true)
    {
        cout<<"consumer:"<<data--<<endl;
        sleep(1);
    }
}

void StartConsumer(vector<Thread<int>>* threads,int threadnum)
{
    for(int i=0;i<threadnum;i++)
    {
        string threadname="thread -"+to_string(i+1);

        Thread<int> t(Consumer,g_data,threadname);
        threads->push_back(t);
        //threads->emplace_back(Consumer,g_data,threadname);

        //启动vector中最后一个线程
        threads->front().Start();//插入的线程对象必为vector中尾部的元素

    }
}

void Productor(int& data)
{
    while(true)
    {
        cout<<"productor:"<<data--<<endl;
        sleep(1);
    }
}

void StartProductor(vector<Thread<int>>* threads,int threadnum)
{
    for(int i=0;i<threadnum;i++)
    {
        string threadname="thread -"+to_string(i+1);

        threads->emplace_back(Productor,g_data,threadname);

        //启动vector中最后一个线程
        threads->back().Start();//插入的线程对象必为vector中尾部的元素

    }
}

void WaitAllThread(vector<Thread<int>>& threads)
{
    for(auto& thread:threads)
    {
        thread.Join();
    }
}
int main()
{
    vector<Thread<int>> threads;
    StartConsumer(&threads,1);  //1.启动消费者线程(单消费)
    StartProductor(&threads,1); //2.启动生产者线程(单生产)
    //单消费单生产模型只需要维护生产者与消费者的关系:互斥&&同步
    WaitAllThread(threads);  //3.回收所有线程
    return 0;
}
*/

/*
void Consumer(BlockQueue * &bq) // 引用指针变量
{
    while (true)
    {
        cout << "consumer:" << bq << endl;
        sleep(1);
    }
}

void Productor(BlockQueue * &bq)
{
    while (true)
    {
        cout << "productor:" << bq<<endl;
        sleep(1);
    }
}

// 提取StartConsumer()与StartProductor()函数的公共方法,增加func_t func函数统一生产者与消费者的执行方法
void StartCommon(vector<Thread<BlockQueue *>> *threads, int threadnum, BlockQueue *bq, func_t<BlockQueue *> func)
{
    for (int i = 0; i < threadnum; i++)
    {
        string threadname = "thread -" + to_string(i + 1);
        Thread<BlockQueue *> t(func, bq, threadname);
        threads->push_back(t);
        threads->back().Start();
    }
}
void StartConsumer(vector<Thread<BlockQueue *>> *threads, int threadnum, BlockQueue *bq)
{
    StartCommon(threads, threadnum, bq, Consumer);
}

void StartProductor(vector<Thread<BlockQueue *>> *threads, int threadnum, BlockQueue *bq)
{
    StartCommon(threads, threadnum, bq, Productor);
}

void WaitAllThread(vector<Thread<BlockQueue *>> &threads)
{
    for (auto &thread : threads)
    {
        thread.Join();
    }
}

int main()
{
    // 1.传递阻塞队列的指针,消费者与生产者访问同一个阻塞队列
    BlockQueue *bq = new BlockQueue();

    // 2.生产者向阻塞队列中放数据,消费者从阻塞队列中获取数据,所以线程的数据类型为阻塞队列
    vector<Thread<BlockQueue *>> threads;
    StartConsumer(&threads, 1, bq);
    StartProductor(&threads, 1, bq);
    WaitAllThread(threads);
    return 0;
}
*/

void Consumer(BlockQueue<int> &bq) 
{
    while (true)
    {
        int data;
        bq.DeQueue(&data);
        cout << "consumer get data:" << data << endl;
    }
}

void Productor(BlockQueue<int> &bq)
{
    int cnt = 1;
    while (true)
    {
        bq.EnQueue(cnt);
        cout << "productor product data: " << cnt << endl;
        cnt++;
        sleep(1);
    }
}

// 提取StartConsumer()与StartProductor()函数的公共方法,增加func_t func函数统一生产者与消费者的执行方法
void StartCommon(vector<Thread<BlockQueue<int>>> *threads, int threadnum, BlockQueue<int> &bq, func_t<BlockQueue<int>> func)
{
    for (int i = 0; i < threadnum; i++)
    {
        string threadname = "thread -" + to_string(i + 1);
        Thread<BlockQueue<int>> t(func, bq, threadname);
        threads->push_back(t);
        threads->back().Start();
    }
}
void StartConsumer(vector<Thread<BlockQueue<int>>> *threads, int threadnum, BlockQueue<int> &bq)
{
    StartCommon(threads, threadnum, bq, Consumer);
}

void StartProductor(vector<Thread<BlockQueue<int>>> *threads, int threadnum, BlockQueue<int> &bq)
{
    StartCommon(threads, threadnum, bq, Productor);
}

void WaitAllThread(vector<Thread<BlockQueue<int>>> &threads)
{
    for (auto &thread : threads)
    {
        thread.Join();
    }
}

int main()
{
    // 1.传递阻塞队列的指针,消费者与生产者访问同一个阻塞队列
    BlockQueue<int> *bq = new BlockQueue<int>(5);

    // 2.生产者向阻塞队列中放数据,消费者从阻塞队列中获取数据,所以线程的数据类型为阻塞队列
    vector<Thread<BlockQueue<int>>> threads;
    StartConsumer(&threads, 1, *bq);
    StartProductor(&threads, 1, *bq);
    WaitAllThread(threads);
    return 0;
}